// Copyright (c) 2021 Presto Labs Pte. Ltd.
// Author: daniel

#include "coin2/exchange/gopax/api_util/auth_key.h"

#include <nlohmann/json.hpp>

#include "coin2/base/string_util.h"
#include "coin2/exchange/base/api_util/api_signature.h"
#include "coin2/exchange/base/api_util/nonce_manager.h"

auto GopaxBaseAuth::GetHeaderSet(
    std::string_view method,
    std::string_view path,
    std::string_view payload,
    int64_t recv_window) -> const HeaderSet& {
  CHECK_THROW(!header_set_.empty()) << "Header set is empty";
  auto timestamp = std::to_string(GetCurrentTimestamp() / 1000000);
  auto recv_window_str = recv_window > 0 ? std::to_string(recv_window) : "";
  auto plain_text = fmt::format("t{}{}{}{}{}", timestamp, method, path, recv_window_str, payload);
  auto signature = ApiSignatureUtil::GetSignatureByHmacSHA512(plain_text, decoded_secret_key_);
  header_set_[0].second = access_key_;
  header_set_[1].second = timestamp;
  header_set_[2].second = signature;
  return header_set_;
}

std::string GopaxWsAuth::AppendAuthParams(std::string_view path) {
  auto header_set = GetHeaderSet("", "", "", 0);
  return fmt::format(
      "{}?apiKey={}&timestamp={}&signature={}",
      path,
      ApiSignatureUtil::EscapeURL(header_set[0].second),
      header_set[1].second,
      ApiSignatureUtil::EscapeURL(header_set[2].second));
}

AsioHttpContext* GopaxRestAuth::CreateRequestByGetWithSignature(
    const std::string& address,
    UrlParamsBuilder* builder) {
  std::string query_string = builder->ComputeQueryString();
  CHECK_THROW(builder->ComputePostBody().empty()) << "It is GET Method, No Payload";
  std::string target = address;
  if (!query_string.empty()) {
    target += "?" + query_string;
  }
  std::string_view path = address;
  if (StringStartsWith(address, "/orders")) {
    path = target;
  }
  auto ahc =
      AsioHttpContext::NewGet(host_, port_, bind_ip_, target, GetHeaderSet("GET", path, "", 0));
  ahc->keep_user_agent = true;

  return ahc;
}

AsioHttpContext* GopaxRestAuth::CreateRequestByPostWithSignature(
    const std::string& address,
    UrlParamsBuilder* builder) {
  std::string query_string = builder->ComputeQueryString();
  std::string post_body = builder->ComputePostBody();
  std::string target = address;
  if (!query_string.empty()) {
    target += "?" + query_string;
  }
  auto ahc = AsioHttpContext::NewPost(
      host_,
      port_,
      bind_ip_,
      target,
      GetHeaderSet("POST", address, post_body, 0),
      post_body);
  ahc->keep_user_agent = true;

  return ahc;
}

AsioHttpContext* GopaxRestAuth::CreateRequestByDeleteWithSignature(
    const std::string& address,
    UrlParamsBuilder* builder) {
  std::string query_string = builder->ComputeQueryString();
  std::string post_body = builder->ComputePostBody();
  std::string target = address;
  if (!query_string.empty()) {
    target += "?" + query_string;
  }
  auto ahc = AsioHttpContext::NewDelete(
      host_,
      port_,
      bind_ip_,
      target,
      GetHeaderSet("DELETE", address, post_body, 0),
      post_body);
  ahc->keep_user_agent = true;

  return ahc;
}
